<?php

declare(strict_types=1);

namespace addons\Builder\driver\trait;

use think\App;
use think\Response;
use think\helper\Str;
use think\facade\Cache;
use think\facade\Cookie;
use think\facade\Session;
use think\wenhainan\Auth;
use app\common\model\Logs;
use app\common\model\Menu;
use app\common\tool\Result;
use app\common\controller\Config;
use app\common\model\Admin as AdminModel;
use think\exception\HttpResponseException;

trait Admin
{
    protected $app;

    protected $request;
    /**
     * @var string 登录标识key
     */
    protected $session_id = 'admin_id';

    /**
     * @var string 登录密码标识key
     */
    protected $session_token = 'password_token';

    /**
     * @var string 账号客户端登录标识
     */
    protected $local_token = 'local_token';


    public function __construct(App $app)
    {
        $this->app = $app;
        $this->request = $app->request;
    }

    /**
     * @return Response
     * 登录方法
     */
    public function login(): Response
    {
        try {

            $param = $this->request->post();

            $validate = validate('Common');
            if (!$validate->scene('login')->check($param)) {
                return Result::fail($validate->getError());
            }
            unset($param['captcha']);
            $param['password'] = md5($param['password']);

            $admin = AdminModel::where($param)->field('id,status,admin_name,password')->find();

            if (empty($admin)) {
                return Result::fail('账号不存在或密码错误');
            }
            if ($admin['status'] != 1) {
                return Result::fail('账号已停用');
            }
            $admin->last_time = time();
            $admin->save();

            Session::set($this->session_id, $admin->id);
            Session::set($this->session_token, md5($admin->password));
            Cookie::set($this->local_token, Str::random(32, 0));
            Logs::adds("后台账号【{$admin->admin_name}】登录了系统");
            return Result::success('登录成功，正在跳转...');
        } catch (\Exception $e) {
            return Result::fail($e->getMessage());
        }
    }

    /**
     * @return Response
     * 退出登录
     */
    public function logout(): Response
    {
        try {
            $admin_id = Session::get($this->session_id);
            if ($admin_id) {
                $admin = AdminModel::where('id', $admin_id)->find();
                Logs::adds("后台账号【{$admin->admin_name}】退出登录");
            }
            $this->clear();
            return Result::success('已退出');
        } catch (\Exception $e) {
            return Result::fail($e->getMessage());
        }
    }

    /**
     * @return void
     * 清除登录标识等
     */
    public function clear(): void
    {
        Session::delete($this->session_id);
        Session::delete($this->session_token);
        Cookie::delete($this->local_token);
    }


    /**
     * @return object|\think\Request|\think\response\Redirect|null
     * 操作验证
     */
    public function verify(): object|array
    {
        try {
            $sessionId = Session::get($this->session_id);
            $localToken = Cookie::get($this->local_token);
            $redirectUrl = url('login/index')->build();

            if (!$this->request->controller()) {
                [$controller, $action] = explode('/', strtolower($this->request->rule()->getRule()));
            } else {
                $controller = strtolower($this->request->controller());
                $action = strtolower($this->request->action());
            }

            if ($controller != 'Login' && (!$sessionId || !$localToken)) {
                return ['type' => 1, 'url' => $redirectUrl];
            }

            //初始化系统参数
            $this->request->system = Cache::get('system');
            if (!$this->request->system) {
                $this->request->system = Config::lists();
                Cache::set('system', $this->request->system);
            }
            //初始化管理员
            $this->request->admin = AdminModel::where(['id' => $sessionId, 'status' => 1])->find();
            if (empty($this->request->admin) || !$this->passwordVerify($this->request->admin)) {
                $this->clear();
                return ['type' => 1, 'url' => $redirectUrl];
            }
            //当前控制器/方法
            $url = $controller . '/' . $action;
            //初始化菜单名称
            $nav = Menu::getNavigation($url);
            //参数传递
            $this->request->nav = $nav;
            $this->request->controller = $controller;
            $this->request->action = $action;

            //超级管理员无需验证
            if ($this->request->admin->role_id == 1) {
                return $this->request;
            }
            //检测无需验证控制器和方法名
            if (!$this->allowVerify($controller, $action) && $this->masterVerify($nav)) {
                //简易权限验证
                $rules = $this->request->admin->role->rules ?? '';
                if (empty($rules) || !in_array($nav['id'], explode(',', $rules))) {
                    return ['type' => -1, 'msg' => '您没有操作权限'];
                }
            }
            return $this->request;
        } catch (\Exception $e) {
            return ['type' => -1, 'msg' => $e->getMessage()];
        }
    }


    /**
     * @param $admin
     * @return bool
     * 验证密码是否进行修改
     */
    public function passwordVerify($admin): bool
    {
        try {
            $password_token = Session::get($this->session_token);
            if (!$password_token) {
                $this->clear();
                return false;
            }

            if (md5($admin->password) != $password_token) {
                $this->clear();
                return false;
            }
            return true;
        } catch (\Exception $e) {
            return false;
        }
    }


    /**
     * @param $controller
     * @param $action
     * @return bool
     * 原点 2022年3月8日15:41:29 无需验证控制器/方法名检测
     */
    public function allowVerify($controller, $action): bool
    {
        if (!empty($this->allow)) {
            foreach ($this->allow as $v) {
                [$c, $a] = explode('/', $v);
                $compare = $c != '*' ? $controller : '*';
                $compare_action = $a != '*' ? $action : '*';
                if ($compare == strtolower($c) && $compare_action == strtolower($a)) {
                    return true;
                }
            }
            return false;
        }
        return true;
    }

    /**
     * @param $url
     * @return bool
     * 原点 2022年3月8日15:42:11 主验证 - 仅验证二级菜单，不验证三级及以上
     */
    public function masterVerify($nav): bool
    {
        return $nav['s_nav'] == '未知' ? false : true;
    }

    public function error($msg = '', string $url = null, $data = '', int $wait = 86400, array $header = []): Response
    {
        if (is_null($url)) {
            $url = request()->isAjax() ? '' : 'javascript:history.back(-1);';
        } elseif ($url) {
            $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : app('route')->buildUrl($url);
        }

        $result = [
            'code' => 0,
            'msg'  => $msg,
            'data' => $data,
            'url'  => $url,
            'wait' => $wait,
        ];

        $type = (request()->isJson() || request()->isAjax()) ? 'json' : 'html';

        // 所有form返回的都必须是json，所有A链接返回的都必须是Html
        $type = request()->isGet() ? 'html' : $type;

        if ($type == 'html') {
            $response = view((string)app('config')->get('app.dispatch_error_tmpl'), $result);
        } else if ($type == 'json') {
            $response = json($result);
        }

        throw new HttpResponseException($response);
    }
}
